package core.proto.rightwindow;

import static app.constants.CollabVizConstants.ENCODING;

import java.awt.Point;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ConcurrentModificationException;
import java.util.Properties;

import javax.swing.JTextPane;
import javax.swing.text.BadLocationException;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;

import core.proto.InfoViz;

public class PostItNetworking {
	
	//PostIt for this instance
	PostIt p;
	
	private static final String OWNERTOKEN = "token";
	private static final String SENDERTOKEN = "sender"; 
	private static final String OWNERNAME = "ownername"; 
	private static final String SESSIONID = "sid";
	private static final String SCREENX = "x";
	private static final String SCREENY = "y";
	private static final String DOCNAME = "docname";
	private static final String USERTEXT = "usertext";
	private static final String UPDATETIME = "lastupdate";
	private static final String GROUP = "group";
	private static final String LOCALSHARING = "localsharing";
	private static final String SINGLELINKS_IN = "singlelinks_in";
	private static final String SINGLELINKS_OUT = "singlelinks_out";
	private static final String GROUPLINKS_IN = "grouplinks_in";
	private static final String GROUPLINKS_OUT = "grouplinks_out";
	private static final String MINIMIZE = "minimized";
	private static final String FONTS = "fonts";
	private static final String TODELETE = "todelete";
	public static final String SHOULDSHARE = "shouldshare";
	
	//Change listener variables
	private String oldScreenX = "0";
	private String oldScreenY = "0";
	private String oldUserText = "";
	public String oldGroup = "";
	private String oldSingleLinksOut = "";
	private String oldSingleLinksIn = "";
	private String oldGroupLinksOut = "";
	private String oldGroupLinksIn = "";
	private String oldMinimize = "false";
	private String oldToDelete = "false";
	
	public boolean threadRepeat = true;
	
	private Properties properties = new Properties();

	public PostItNetworking(PostIt p){
		this.p = p;
		
		postItChangeListener();
	}
	
	public void postItChangeListener(){
		new Thread(
	            new Runnable() {
	            	public void run() {
	            		while(threadRepeat){
	            			
	            			synchronized(BoardPane.lock){
	            				try{
	            					properties.put(SCREENX, Integer.toString(p.getX()));
	            					properties.put(SCREENY, Integer.toString(p.getY()));
	            					properties.put(USERTEXT, p.getText());
	            					properties.put(GROUP, p.getGroup());
	            					properties.put(SINGLELINKS_OUT, BoardPane.getInstance().getSingleLinksStringOut(p));
	            					properties.put(SINGLELINKS_IN, BoardPane.getInstance().getSingleLinksStringIn(p));
	            					properties.put(GROUPLINKS_OUT, BoardPane.getInstance().getGroupLinkStringOut(p));
	            					properties.put(GROUPLINKS_IN, BoardPane.getInstance().getGroupLinkStringIn(p));
	            					properties.put(MINIMIZE, ((Boolean)p.miniState).toString());
	            					properties.put(TODELETE, "" + p.toDelBool);
	            					
	            					String newScreenX = Integer.toString(p.getX());
	            					String newScreenY = Integer.toString(p.getY());
	            					String newUserText = p.getText();
	            					String newGroup = p.getGroup();
	            					String newSingleLinksOut = BoardPane.getInstance().getSingleLinksStringOut(p);
	            					String newSingleLinksIn = BoardPane.getInstance().getSingleLinksStringIn(p);
	            					String newGroupLinksOut = BoardPane.getInstance().getGroupLinkStringOut(p);
	            					String newGroupLinksIn = BoardPane.getInstance().getGroupLinkStringIn(p);
	            					String newMinimize = ((Boolean)p.miniState).toString();
	            					String newToDelete = "" + p.toDelBool;
	            					
	            					boolean updateBool = false;
	            					
	            						if(!oldScreenX.equals(newScreenX) && !p.dragEnabled && !p.toDelBool){
	            							System.out.println("%%%%% Update by screen x from old: " + oldScreenX + " to new: " + newScreenX);
	            							LeftRightCommunicator.postItUpdated(p);
	            							updateBool = true;
	            						}
	            						else if(!oldScreenY.equals(newScreenY) && !p.dragEnabled && !p.toDelBool){
	            							System.out.println("%%%%% Update by screen y");
	            							LeftRightCommunicator.postItUpdated(p);
	            							updateBool = true;
	            						}
	            						else if(!oldUserText.equals(newUserText) && p.userTextTimerBool){
	            							System.out.println("%%%%% Update by user text");
	            							LeftRightCommunicator.postItUpdated(p);
	            							updateBool = true;
	            						}
	            						else if(!oldGroup.equals(newGroup)){
	            							System.out.println("%%%%% Update by group change w/ text " + p.getText());
	            							LeftRightCommunicator.postItUpdated(p);
	            							updateBool = true;
	            						}
	            						else if(!oldSingleLinksOut.equals(newSingleLinksOut)){
	            							System.out.println("%%%%% Update by single links out");
	            							LeftRightCommunicator.postItUpdated(p);
	            							updateBool = true;
	            						}
	            						else if(!oldSingleLinksIn.equals(newSingleLinksIn)){
	            							System.out.println("%%%%% Update by single links in");
	            							LeftRightCommunicator.postItUpdated(p);
	            							updateBool = true;
	            						}
	            						else if(!oldGroupLinksOut.equals(newGroupLinksOut)){
	            							System.out.println("%%%%% Update by group links out");
	            							LeftRightCommunicator.postItUpdated(p);
	            							updateBool = true;
	            						}
	            						else if(!oldGroupLinksIn.equals(newGroupLinksIn)){
	            							System.out.println("%%%%% Update by group links in");
	            							LeftRightCommunicator.postItUpdated(p);
	            							updateBool = true;
	            						}
	            						else if(!oldMinimize.equals(newMinimize)){
	            							System.out.println("%%%%% Update by minimize");
	            							LeftRightCommunicator.postItUpdated(p);
	            							updateBool = true;
	            						}
	            						else if(!oldToDelete.equals(newToDelete)){
	            							System.out.println("%%%%% Update by to delete");
	            							LeftRightCommunicator.postItUpdated(p);
	            							updateBool = true;
	            						}
	            					
	            					if(updateBool){
	            						oldScreenX = newScreenX;
	            						oldScreenY = newScreenY;
	            						oldUserText = newUserText;
	            						oldGroup = newGroup;
	            						oldSingleLinksOut = newSingleLinksOut;
	            						oldSingleLinksIn = newSingleLinksIn;
	            						oldGroupLinksOut = newGroupLinksOut;
	            						oldGroupLinksIn = newGroupLinksIn;
	            						oldMinimize = newMinimize;
	            						oldToDelete = newToDelete;
	            					}
	            				}
	            				catch(ConcurrentModificationException e){
	            					
	            				}
	            				catch(NullPointerException e){
	            					
	            				}
	            			}
	            			
	            		}
	                }
	            }).start();
	}
	
	/**
	 * Makes changes to the postit fields manually in order to prevent
	 * prevent its info from being sent over the network.
	 */
	public void oldNewUpdate(){
		oldScreenX = Integer.toString(p.getX());
		oldScreenY = Integer.toString(p.getY());
		oldUserText = p.getText();
		oldGroup = p.getGroup();
		oldSingleLinksOut = BoardPane.getInstance().getSingleLinksStringOut(p);
		oldSingleLinksIn = BoardPane.getInstance().getSingleLinksStringIn(p);
		oldGroupLinksOut = BoardPane.getInstance().getGroupLinkStringOut(p);
		oldGroupLinksIn = BoardPane.getInstance().getGroupLinkStringIn(p);
		oldMinimize = ((Boolean)p.miniState).toString();
		oldToDelete = "" + p.toDelBool;
	}
	
	public String toNetworkString () throws IOException {
		properties.clear();
		properties.put(SESSIONID, ((Long)p.getSessionId()).toString());
		properties.put(OWNERTOKEN, p.getOwner().toString());
		properties.put(SENDERTOKEN, InfoViz.userToken);
		properties.put(DOCNAME, p.getDocName());
		properties.put(SCREENX, Integer.toString(p.getX()));
		properties.put(SCREENY, Integer.toString(p.getY()));
		properties.put(UPDATETIME, p.lastUpdateTime.toString());
		properties.put(USERTEXT, p.getText());
		properties.put(GROUP, p.getGroup());
		properties.put(SINGLELINKS_OUT, BoardPane.getInstance().getSingleLinksStringOut(p));
		properties.put(SINGLELINKS_IN, BoardPane.getInstance().getSingleLinksStringIn(p));
		properties.put(GROUPLINKS_OUT, BoardPane.getInstance().getGroupLinkStringOut(p));
		properties.put(GROUPLINKS_IN, BoardPane.getInstance().getGroupLinkStringIn(p));
		properties.put(MINIMIZE, ((Boolean)p.miniState).toString());
		properties.put(FONTS, p.getFontNetworkString());
		properties.put(TODELETE, "" + p.toDelBool);
		properties.put(SHOULDSHARE, "" + p.shouldShare());
		properties.put(LOCALSHARING, p.getLocalSharing() + "");
		
		ByteArrayOutputStream stream = new ByteArrayOutputStream();
		properties.store(stream, null);
		return stream.toString(ENCODING);
	}
	
	public static String getSenderToken(Properties prop) {
		return (String) prop.get(SENDERTOKEN);
	}
	
	public static String getSenderName(Properties prop) {
		return (String) prop.get(OWNERNAME);
	}

	public static String getOwnerToken(Properties prop) {
		return (String) prop.get(OWNERTOKEN);
	}
	
	public static boolean getSharingDiscretion(Properties prop){
		if(((String)prop.get(SHOULDSHARE)).equals("true")){
			return true;
		}
		return false;
	}

	public static long getSid (Properties prop) {
		return Long.valueOf((String) prop.getProperty(SESSIONID));
	}

	public static String getUniqueKey (Properties prop) {
		return  prop.getProperty(OWNERTOKEN).toString() + prop.getProperty(SESSIONID).toString();
	}
	
	public static String getDocName(Properties prop){
		return prop.getProperty(DOCNAME);
	}

	public static String getMessage (Properties prop) {
		return prop.getProperty(USERTEXT);
	}

	public static Point getLocation (Properties prop) {
		return new Point(Integer.valueOf(prop.get(SCREENX).toString()), Integer.valueOf(prop.get(SCREENY).toString()));
	}
	
	public static String getGroup (Properties prop) {
		return prop.getProperty(GROUP);
	}
	
	public static String getLocalSharing(Properties prop){
		return prop.getProperty(LOCALSHARING);
	}
	
	public static void loadFonts(Properties prop, JTextPane pane){
		String fontString = prop.getProperty(FONTS);
		String paneText = null;
		try {
			paneText = pane.getStyledDocument().getText(0, pane.getStyledDocument().getLength());
		} catch (BadLocationException e1) {
			e1.printStackTrace();
		}
				
		pane.setText("");
		
		int lastPos = 0;
		
		int curPos;
		
		if(!fontString.equals("")){
			String[] changes = fontString.split("\\|");
			
			for(String change : changes){
				change.replace("|", "");
				change.trim();
				
				SimpleAttributeSet attributes = new SimpleAttributeSet();
				
				if(change.charAt(0) == 'B'){
					StyleConstants.setBold(attributes, true);
				}
				else{
					StyleConstants.setBold(attributes, false);
				}
				if(change.charAt(1) == 'I'){
					StyleConstants.setItalic(attributes, true);
				}
				else{
					StyleConstants.setItalic(attributes, false);
				}
				if(change.charAt(2) == 'U'){
					StyleConstants.setUnderline(attributes, true);
				}
				else{
					 StyleConstants.setUnderline(attributes, false);
				}
			   
			    curPos = Integer.parseInt(change.substring(3));
			    
			    String strOut = "";
			    
			    //HACK TO INCLUDE LAST CHARACTER
			    try{
				    if(curPos == paneText.length() - 1){
				    	curPos++;
				    }
				    strOut = paneText.substring(lastPos, curPos);
			    }
			    catch(StringIndexOutOfBoundsException e){
			
			    }
			    
			    try {
					pane.getStyledDocument().insertString(lastPos, strOut, attributes);
				} catch (BadLocationException e) {
					e.printStackTrace();
				}
			    
			    lastPos = curPos;
			}
		}
	}
	
	public static boolean getMinimize(Properties prop){
		if(prop.getProperty(MINIMIZE).equals("true")){
			return true;
		}
		else{
			return false;
		}
	}
	
	public static boolean getToDelete(Properties prop){
		if(prop.getProperty(TODELETE).equals("true")){
			return true;
		}
		else{
			return false;
		}
	}
	
	public static JTextPane getFontWeightedPane(JTextPane tp, Properties prop){
		String fontString = prop.getProperty(FONTS);
		String[] changes = fontString.split("\\|");
		
		for(String change : changes){
			change.replace("\\|", "");
			String[] changeArr = change.split("@");
			
			//FONTS
			changeArr[0] = changeArr[0].replace("@", "");
			
			//LOCATION
			changeArr[1] = changeArr[1].replace("@", "");
		}
		
		return tp;
	}
}
